package net.mxox.apps.ant;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class EclipseProjectTask extends Task {
	private static final Pattern libFilePattern = Pattern
			.compile("([a-z|A-Z|-]+)-([\\d|\\.]+)\\.(jar)|(zip)");

	private boolean isWeb;

	private int javaVersion;

	public void setJavaVersion(int javaVersion) {
		this.javaVersion = javaVersion;
	}

	public void setWeb(boolean isWeb) {
		this.isWeb = isWeb;
	}

	public void execute() {
		createProject(this.getProject().getName());
		createClassPath();
		createSettings();
	}

	private void createProject(String projectName) {
		try {
			File projectFile = new File(".project");

			if (projectFile.exists()) {
				throw new BuildException(".project file already exists!");
			}

			PrintWriter out = new PrintWriter(projectFile);
			out.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n");

			out.print("<projectDescription>" + "\n");

			out.print("\t" + "<name>" + projectName + "</name>" + "\n");
			out.print("\t" + "<comment></comment>" + "\n");
			out.print("\t" + "<projects>" + "\n");
			out.print("\t" + "</projects>" + "\n");
			out.print("\t" + "<buildSpec>" + "\n");
			out.print("\t\t" + "<buildCommand>" + "\n");
			out.print("\t\t\t"
					+ "<name>org.eclipse.jdt.core.javabuilder</name>" + "\n");
			out.print("\t\t\t" + "<arguments>" + "\n");
			out.print("\t\t\t" + "</arguments>" + "\n");
			out.print("\t\t" + "</buildCommand>" + "\n");
			out.print("\t" + "</buildSpec>" + "\n");
			out.print("\t" + "<natures>" + "\n");
			out
					.print("\t\t"
							+ "<nature>org.eclipse.jdt.core.javanature</nature>"
							+ "\n");
			out.print("\t" + "</natures>" + "\n");

			out.print("</projectDescription>" + "\n");

			out.flush();
			out.close();
		} catch (IOException e) {
			throw new BuildException(e);
		}
	}

	private void createClassPath() {
		String libDir = null;
		String srcDir = null;
		if (isWeb) {
			libDir = "webroot/WEB-INF/lib";
			srcDir = "webroot/WEB-INF/src";
		} else {
			libDir = "lib";
			srcDir = "src";
		}

		String javaContainer = "org.eclipse.jdt.launching.JRE_CONTAINER/"
				+ "org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"
				+ "JavaSE-1.6";
		if (javaVersion == 5) {
			javaContainer = "org.eclipse.jdt.launching.JRE_CONTAINER/"
					+ "org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"
					+ "JavaSE-1.5";
		} else if (javaVersion == 4) {
			javaContainer = "org.eclipse.jdt.launching.JRE_CONTAINER/"
					+ "org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"
					+ "JavaSE-1.4";
		}

		try {
			File classpathFile = new File(".classpath");

			if (classpathFile.exists()) {
				throw new BuildException(".classpath file already exists!");
			}

			PrintWriter out = new PrintWriter(classpathFile);
			out.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n");

			out.print("<classpath>" + "\n");

			// Add src dir to classpath
			out.print("\t<classpathentry kind=\"src\" path=\"" + srcDir
					+ "/main/conf" + "\"/>" + "\n");
			out.print("\t<classpathentry kind=\"src\" path=\"" + srcDir
					+ "/main/java" + "\"/>" + "\n");
			out.print("\t<classpathentry kind=\"src\" path=\"" + srcDir
					+ "/test/conf" + "\"/>" + "\n");
			out.print("\t<classpathentry kind=\"src\" path=\"" + srcDir
					+ "/test/java" + "\"/>" + "\n");

			// Add java container to classpath
			out.print("\t<classpathentry kind=\"con\" path=\"" + javaContainer
					+ "\"/>" + "\n");

			// Add libs to classpath
			File libDirFile = new File(libDir);
			File[] libFileArray = libDirFile.listFiles(new FilenameFilter() {

				public boolean accept(File dir, String name) {
					if (!name.endsWith(".jar") && !name.endsWith(".zip")) {
						return false;
					}

					if (name.contains("sources")) {
						return false;
					}

					return true;
				}
			});
			for (File libFile : libFileArray) {
				String libFileName = libFile.getName();
				Matcher m = libFilePattern.matcher(libFileName);
				if (!m.matches()) {
					continue;
				}
				String libName = m.group(1);
				String libVersion = m.group(2);
				File zipSourceFile = new File(libName + "-" + libVersion + "-"
						+ "sources" + ".zip");
				File jarSourceFile = new File(libName + "-" + libVersion + "-"
						+ "sources" + ".jar");
				if (zipSourceFile.exists()) {
					out.print("\t" + "	<classpathentry kind=\"lib\" path=\""
							+ libDir + "/" + libFile.getName()
							+ "\" sourcepath=\"" + libDir + "/"
							+ zipSourceFile.getName() + "\"/>" + "\n");
				} else if (jarSourceFile.exists()) {
					out.print("\t" + "	<classpathentry kind=\"lib\" path=\""
							+ libDir + "/" + libFile.getName()
							+ "\" sourcepath=\"" + libDir + "/"
							+ jarSourceFile.getName() + "\"/>" + "\n");
				} else {
					out.print("\t" + "<classpathentry kind=\"lib\" path=\""
							+ libDir + "/" + libFile.getName() + "\"/>" + "\n");
				}
			}

			out.print("</classpath>" + "\n");

			out.flush();
			out.close();
		} catch (FileNotFoundException e) {
			throw new BuildException(e);
		}

	}

	private void createSettings() {

		try {
			File settingsFile = new File(".settings");
			if (settingsFile.exists()) {
				throw new BuildException(".settings directory already exists!");
			} else {
				settingsFile.mkdir();
			}

			File corePrefsFile = new File(
					".settings/org.eclipse.core.resources.prefs");

			PrintWriter corePrefsOut = new PrintWriter(corePrefsFile);

			corePrefsOut.print("#Generated by Ant Eclipse Project Task\n");
			corePrefsOut.print("eclipse.preferences.version=1\n");
			corePrefsOut.print("encoding/<project>=UTF-8");

			corePrefsOut.flush();
			corePrefsOut.close();

			File jdtPrefsFile = new File(".settings/org.eclipse.jdt.core.prefs");

			PrintWriter jdtPrefsOut = new PrintWriter(jdtPrefsFile);

			jdtPrefsOut.print("#Generated by Ant Eclipse Project Task\n");
			jdtPrefsOut.print("eclipse.preferences.version=1\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.codegen.targetPlatform=1."
							+ javaVersion + "\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve\n");
			jdtPrefsOut.print("org.eclipse.jdt.core.compiler.compliance=1."
					+ javaVersion + "\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.debug.lineNumber=generate\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.debug.localVariable=generate\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.debug.sourceFile=generate\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\n");
			jdtPrefsOut
					.print("org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\n");
			jdtPrefsOut.print("org.eclipse.jdt.core.compiler.source=1."
					+ javaVersion + "\n");

			jdtPrefsOut.flush();
			jdtPrefsOut.close();
		} catch (FileNotFoundException e) {
			throw new BuildException(e);
		}
	}

	public static void main(String[] args) {
		EclipseProjectTask t = new EclipseProjectTask();
		t.setWeb(false);
		t.setJavaVersion(5);
		t.execute();
	}

}
